/* 专门为构建虚拟节点提供一些方法 */
// h()  _c()
export function createElementVNode(vm, tag, data, ...children) {
  if (data == null) {
    data = {};
  }
  let key = data.key;
  if (key) delete data.key;
  return vnode(vm, tag, key, data, children);
}

// _v()
export function createTextVNode(vm, text) {
  return vnode(vm, undefined, undefined, undefined, undefined, text);
}

// ast一样吗？ast做的是语法层面的转化，描述的是语法本身 (可以描述js css html)
// > es6转成es5 html转成js css转成js
// 我们的虚拟dom是描述的dom元素，可以增加一些自定义属性 (描述dom)
function vnode(vm, tag, key, data, children, text) {
  return {
    vm,
    tag,
    key,
    data,
    children,
    text,
  };
}

// patch既有初始化的功能，又有更新的逻辑
export function patch(oldVNode, VNode) {
  // 判断是不是一个node节点
  const isRealElement = oldVNode.nodeType;
  if (isRealElement) {
    // 是node节点
    const elm = oldVNode;
    // 拿到父节点
    const parentElm = elm.parentNode;
    // 用虚拟dom创建新节点插入旧节点后面
    let newElm = createElm(VNode);
    // console.log(newElm);
    parentElm.insertBefore(newElm, elm.nextSibling);
    // 删掉旧节点
    parentElm.removeChild(elm);

    return newElm;
  } else {
    // 不是node节点，这进行diff算法
  }
}

// 创建真实DOM
export function createElm(VNode) {
  let { tag, data, children, text } = VNode;
  if (typeof tag === "string") {
    // 标签
    // 将创建的真实节点放在虚拟节点中，对应起来
    // > 后续修改属性了，可以找到虚拟节点对应的真实节点来修改属性
    VNode.el = document.createElement(tag);

    // 更新属性
    patchProps(VNode.el, data);

    children.forEach((child) => {
      VNode.el.appendChild(createElm(child));
    });
  } else {
    // 文本
    VNode.el = document.createTextNode(text);
  }
  return VNode.el;
}

// 更新属性
export function patchProps(el, props) {
  for (let key in props) {
    if (key === "style") {
      // style{ color:'red' }
      for (let styleName in props.style) {
        el.style[styleName] = props.style[styleName];
      }
    } else {
      el.setAttribute(key, props[key]);
    }
  }
}
